package com.google.code.krillion.firehose.server;

import static com.google.appengine.api.labs.taskqueue.TaskOptions.Builder.url;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.List;
import java.util.ResourceBundle;
import java.util.logging.Logger;

import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

import com.google.appengine.api.labs.taskqueue.Queue;
import com.google.appengine.api.labs.taskqueue.QueueFactory;
import com.google.code.krillion.firehose.data.MessageStat;
import com.google.code.krillion.firehose.data.PMF;

import twitter4j.DirectMessage;
import twitter4j.Paging;
import twitter4j.Twitter;
import twitter4j.TwitterException;
import twitter4j.TwitterFactory;

public class MessageServlet implements Servlet {
	private static final Logger log = Logger.getLogger(MessageServlet.class.getName());
	private static ServletConfig config;
	private static String username;
	private static String password;
	private static Twitter twitter;
	private static int lastMessage = 0;
	
	private static final int MAX_NEW_MESSAGES = 100;

	@Override
	public void destroy() {
		// Intentionally a noop for the time being.
	}

	@Override
	public ServletConfig getServletConfig() {
		return config;
	}

	@Override
	public String getServletInfo() {
		return null;
	}

	@Override
	public void init(ServletConfig sc) throws ServletException {
		config = sc;

		ResourceBundle bundle = ResourceBundle.getBundle("com.google.code.krillion.firehose.server.krillion");
		username = (String) bundle.getObject("kritter.username");
		password = (String) bundle.getObject("kritter.password");
		if (username != null && password != null) {
			TwitterFactory factory = new TwitterFactory();
		    twitter = factory.getInstance(username,password);
			try {
				twitter.verifyCredentials();
			} catch (TwitterException e) {
				log.severe("TwitterException verifying user credentials: " + e.getMessage());
			}
		}

		PersistenceManager pm = PMF.get().getPersistenceManager();
	    Query query = pm.newQuery(MessageStat.class);
	    query.setOrdering("date desc");
	    query.setRange(0,1);

	    try {
	    	@SuppressWarnings("unchecked")
			List<MessageStat> stats = (List<MessageStat>) query.execute();
			if (stats != null && stats.size() > 0) {
				lastMessage = stats.get(0).getLastMessage();
			}
	    } finally {
	    	query.closeAll();
            pm.close();
	    }
	}

	@Override
	public void service(ServletRequest req, ServletResponse resp)
	throws ServletException, IOException {

		Queue queue = QueueFactory.getQueue("messages");

		resp.setContentType("text/plain");
		PrintWriter writer = resp.getWriter();
		try {
			List<DirectMessage> messages = twitter.getDirectMessages(new Paging((long)lastMessage));
			if (messages != null && messages.size() > 0) {
				int newLastMessage = messages.get(0).getId();
				int newMessageCount = 0;
				for (DirectMessage message : messages) {
					if (newMessageCount < MAX_NEW_MESSAGES) {
						newMessageCount++;
						writer.println(" Friend: " + message.getSenderScreenName());
						writer.println("Message: " + message.getText() + "\n");
						writer.flush();
						queue.add(url("/messages/worker")
								 .param("friend", message.getSenderScreenName())
								 .param("message", message.getText()));
					} else {
						log.severe("reached maximum message limit before processing all new messages");
						break;
					}
				}
				if (newMessageCount > 0) {
					lastMessage = newLastMessage;
					MessageStat stat = new MessageStat(new Date(), newMessageCount, newLastMessage);
					log.info("newLastMessage=" + newLastMessage + ", newMessageCount=" + newMessageCount);
					PersistenceManager pm = PMF.get().getPersistenceManager();
			        try {
			            pm.makePersistent(stat);
			        } finally {
			            pm.close();
			        }
		        }
			} else {
	        	writer.println("No new direct messages to be processed at this time.");
		    	log.info("No new direct messages to be processed at this time.");
	        }
		} catch (TwitterException e) {
			log.severe("TwitterException processing new messages: " + e.getMessage());
		}
		writer.close();
	}

}
